package com.imd.s9.impl;

import com.alibaba.fastjson.JSONObject;
import com.imd.base.BusinessException;
import com.imd.s9.entity.TableInfo;
import com.imd.s9.service.IPreHookService;
import com.imd.s9.util.InitCriteria;
import com.imd.utils.SequenceUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.*;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.print.Doc;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author cuiyu
 * @description
 * @date 2024/7/15 16:50:33
 */
@Service
@Slf4j
public class PreHookImpl implements IPreHookService {
    @Resource
    MongoTemplate mongoTemplate;

    @Resource
    InitCriteria initCriteria;

    @Override
    public Object insert(String templateId, Map entity) throws BusinessException {
        switch (templateId){
            case "68410427e0d8101bcc0eee02":
                String checkPlan = entity.get("检验方案").toString();
                Object checkNum = entity.get("检验数量");
                Object productBatchNo = entity.get("生产批号");
                //Object batchNum = entity.get("批次总量");
                Object incomeNo = entity.get("来料单");
                Document incomeOrder = mongoTemplate.findById(new ObjectId(incomeNo.toString()),Document.class,TableInfo.incomeOrder);

                BigDecimal bg = checkNum==null?new BigDecimal(1):new BigDecimal(entity.get("检验数量").toString());
                Query query = initCriteria.createQuery(Criteria.where("方案编号").is(checkPlan));
                JSONObject jso = mongoTemplate.findOne(query, JSONObject.class, TableInfo.checkPlan);
                String checkWay = jso.getString("检验方式");
                String projectName = jso.getString("项目名称");
                LinkedHashMap<String,ObjectId> materialIds = jso.getObject("物料", LinkedHashMap.class);
                ObjectId id = materialIds.get("id");
                JSONObject material = mongoTemplate.findById(id,JSONObject.class,TableInfo.materialMana);

                List<Document> materials = incomeOrder.get("明细",List.class);
                if(materials==null||materials.isEmpty()){
                    throw new BusinessException("来料单明细不能为空");
                }

                Double batchNum = null;
                for(Document document:materials){
                    if (document.getString("物料编码").equals(material.getString("物料编码"))){
                        if(document.get("数量")==null){
                            throw new BusinessException("来料单中物料数量不能为空");
                        }
                        batchNum = Double.valueOf(document.get("数量").toString());
                    }
                }
                if(batchNum==null){
                    throw new BusinessException("来料单中物料数量不能为空");
                }

                String materialNo = material.getString("物料编码");
                String materialName = material.getString("物料名称");
                List<ObjectId> checkItems = jso.getObject("检验条目",List.class);
                if(checkItems==null||checkItems.isEmpty()){
                    throw new BusinessException("检验方案未填写检验条目");
                }
                for(int i=0;i<bg.intValue();i++){
                    for(ObjectId oid :checkItems){
                        JSONObject checkItem = mongoTemplate.findById(oid,JSONObject.class,TableInfo.checkItem);
                        String checkItemName = checkItem.getString("检验项名称");
                        String standard = checkItem.getString("计算标准");
                        String checkTool = checkItem.getString("检测工具");
                        Boolean caculType = checkItem.get("计算类型")==null?false:checkItem.getBoolean("计算类型");
                        String caculUnite = checkItem.getString("检验值单位");
                        String requirement = checkItem.getString("技术要求");
                        Document document = new Document();
                        document.put("检验方案",checkPlan);
                        document.put("项目名称",projectName);
                        document.put("生产批号",productBatchNo);
                        document.put("来料单号",incomeOrder.getString("单据编号"));
                        document.put("物料",materialNo);
                        document.put("物料名称",materialName);
                        document.put("检验数量",bg.intValue());
                        document.put("检验项名称",checkItemName);
                        document.put("检验方式",checkWay);
                        document.put("计算类型",caculType);
                        document.put("计算标准",standard);
                        document.put("检验值单位",caculUnite);
                        document.put("检测工具",checkTool);
                        document.put("技术要求",requirement);
                        document.put("批次总量",batchNum);
                        document.put("检验结果","不合格");
                        document.put("isDelete",0);
                        document.put("tenantId",TableInfo.tenantId);
                        document.put("createTime",new Date());
                        document.put("createName",entity.get("createName"));
                        mongoTemplate.save(document,TableInfo.checkData);
                    }
                }

                throw new BusinessException(1111,"请填充测试数据");
                //break;
            case "683fffdae0d8101bcc0eedd5":
                String incomeId = entity.get("来料单").toString();
                Document document1 = mongoTemplate.findById(new ObjectId(incomeId),Document.class,TableInfo.incomeOrder);
                String project = document1.getString("项目名称");
                String income = document1.getString("单据编号");
                if (StringUtils.isEmpty(project)) {
                    throw new BusinessException("项目名称不能为空");
                }

                Query isExists = new Query(Criteria.where("tenantId").is(TableInfo.tenantId)
                        .and("isDelete").is(0).and("来料单号").is(income)
                );
                if(mongoTemplate.exists(isExists,TableInfo.checkReport)){
                    throw new BusinessException("该来料单已存在");
                }

                MatchOperation matchOperation = Aggregation.match(Criteria.where("来料单号").is(income).and("tenantId")
                        .is(TableInfo.tenantId).and("isDelete").is(0));

                //GroupOperation groupOperation = Aggregation.group("生产批号","物料","检验结果").count().as("检验结果");
                // 1. 按批次和物料分组，标记不合格项为1，0合格
                GroupOperation groupOperation = Aggregation.group("生产批号","物料","产品名称")
                        .max(ConditionalOperators
                                .when(Criteria.where("检验结果").is("不合格"))
                                .then(1)
                                .otherwise(0)
                        ).as("是否合格")
                        .first("批次总量").as("批次总量")
                        .first("物料名称").as("物料名称")
                        .first("检验方式").as("抽检方式")
                        ;

                // 2. 标记物料合格状态
                ProjectionOperation projectStatus = Aggregation.project()
                        .and("_id.生产批号").as("生产批号")
                        .and("_id.物料").as("物料")
                        .and("_id.产品名称").as("产品名称")
                        .and("是否合格").as("是否合格")
                        .and("抽检方式").as("抽检方式")
                        .and("物料名称").as("物料名称")
                        .and("批次总量").as("批次总量");

                // 4. 按批次物料统计不合格数物料
                GroupOperation groupByBatch = Aggregation.group("生产批号","物料")
                        .sum("是否合格").as("不合格数")
                        .count().as("检验数量")
                        .first("抽检方式").as("抽检方式")
                        .first("物料名称").as("物料名称")
                        .first("批次总量").as("批次总量");

                ProjectionOperation markQualifiedStatus = Aggregation.project()
                        .and("_id.生产批号").as("生产批号")
                        .and("_id.物料").as("物料")
                        .and("不合格数").as("不合格数")
                        .and("检验数量").as("检验数量")
                        .and("批次总量").as("批次总量")
                        .and("抽检方式").as("抽检方式")
                        .and("物料名称").as("物料名称")
                        .and(ArithmeticOperators.valueOf("检验数量").subtract("不合格数")).as("合格数")
                        ;
                // 构建聚合管道
                Aggregation aggregation = Aggregation.newAggregation(matchOperation,
                        groupOperation,
                        projectStatus,
                        groupByBatch,
                        markQualifiedStatus
                );
                AggregationResults<Document> results = mongoTemplate.aggregate(
                        aggregation,TableInfo.checkData,Document.class);
                List<Document> list = results.getMappedResults();
                List<Document> details = new ArrayList();
                details = list.stream().map(t->{
                    Document document = new Document();
                    document.put("生产批号",t.get("生产批号"));
                    document.put("物料",t.get("物料"));
                    document.put("物料名称",t.get("物料名称"));
                    document.put("批次总量",t.get("批次总量"));
                    document.put("检验数量",t.get("检验数量"));
                    document.put("合格数",t.get("合格数"));
                    document.put("不合格数",t.get("不合格数"));
                    document.put("抽检方式",t.get("抽检方式"));
                    return document;
                }).collect(Collectors.toList());
                Document document = new Document();
                document.put("报告名称",entity.get("报告名称"));
                document.put("单据编号", SequenceUtil.getSequence("BG"));
                document.put("项目名称",project);
                document.put("来料单号",income);
                document.put("检验明细",details);
                document.put("备注",entity.get("备注"));
                document.put("isDelete",0);
                document.put("tenantId",TableInfo.tenantId);
                document.put("createTime",new Date());
                document.put("createName",entity.get("createName"));
                mongoTemplate.save(document,TableInfo.checkReport);
                throw new BusinessException(1111,"");
        }
        return null;
    }

    @Override
    public Object delete(String templateId, String entityId) throws BusinessException {
        return null;
    }

    @Override
    public Object update(String templateId, Map entity) throws BusinessException {
        return null;
    }

}
